﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AudiPyme.DAL;

namespace AudiPyme.BLL
{
    public class ControlesEmpresaInformeNegocio
    {
        //Método que se usa en el informe de empresa para saber la situación de los controles de un informe asociado a la empresa,
        //según su nivel de madurez, para ver su % de cumplimiento y dar una visión clara de la distribución de controles
        //que define el nivel de madurez actual de una empresa
        public static List<PuntoDoubleXY> ControlesNivelMadurezEmpresaInformeXY(int IdInforme)
        {
            List<PuntoDoubleXY> LPuntos = new List<PuntoDoubleXY>();
            //Recogemos los controles del informe perteneciente a la empresa asociados a el nivel de madurez de cada uno
            List<ControlesCheckList> LCtrChkListEmpresa = ControlesEmpresaNegocio.RecogeControlesCheckListInforme(IdInforme);
            if (LCtrChkListEmpresa.Count == 133)
            {
                //Con los controles ya de la empresa, los divididos segun su respuesta y nivel de madurez
                List<int> ControlesSINivelMadurez = new List<int>(3);
                ControlesSINivelMadurez = EmpresasNegocio.NumeroControlesSiNiveles(LCtrChkListEmpresa);
                List<int> ControlesNONivelMadurez = new List<int>(3);
                ControlesNONivelMadurez = EmpresasNegocio.NumeroControlesNoNiveles(LCtrChkListEmpresa);
                List<int> ControlesPARCNivelMadurez = new List<int>(3);
                ControlesPARCNivelMadurez = EmpresasNegocio.NumeroControlesParcialmenteNiveles(LCtrChkListEmpresa);
                List<int> ControlesNANivelMadurez = new List<int>(3);
                ControlesNANivelMadurez = EmpresasNegocio.NumeroControlesNoAplicaNiveles(LCtrChkListEmpresa);
                List<int> NumCtrlNivMadurez = new List<int>(3);
                //Numero Total de Controles por cada nivel
                NumCtrlNivMadurez = ControlesFactory.NumeroControlesTotalesNiveles();
                //Creamos Puntos por cada parámetro y tomando como Serie el Nivel de Madurez
                for (int i = 0; i < 3; i++)
                {
                    String SNumContrNivMadurez = "Total";
                    double DNumContrNivMadurez = NumCtrlNivMadurez[i];
                    PuntoDoubleXY PuntoNumContr = new PuntoDoubleXY(SNumContrNivMadurez, DNumContrNivMadurez, "Nivel " + (i + 1));
                    LPuntos.Add(PuntoNumContr);
                    String SNumContrSINivMad = "Si";
                    double DNumContrSINivMad = ControlesSINivelMadurez[i];
                    PuntoDoubleXY PuntoContrSI = new PuntoDoubleXY(SNumContrSINivMad, DNumContrSINivMad, "Nivel " + (i + 1));
                    LPuntos.Add(PuntoContrSI);
                    //Falta el No, el PARCIALMENTE, EL N/A y el porcentaje
                    String SNumContrNONivMad = "No";
                    double DNumContrNONivMad = ControlesNONivelMadurez[i];
                    PuntoDoubleXY PuntoContrNO = new PuntoDoubleXY(SNumContrNONivMad, DNumContrNONivMad, "Nivel " + (i + 1));
                    LPuntos.Add(PuntoContrNO);
                    String SNumContrPARCNivMad = "Parcialmente";
                    double DNumContrPARCNivMad = ControlesPARCNivelMadurez[i];
                    PuntoDoubleXY PuntoContrPARC = new PuntoDoubleXY(SNumContrPARCNivMad, DNumContrPARCNivMad, "Nivel " + (i + 1));
                    LPuntos.Add(PuntoContrPARC);
                    String SNumContrNANivMad = "No Aplica";
                    double DNumContrNANivMad = ControlesNANivelMadurez[i];
                    PuntoDoubleXY PuntoContrNA = new PuntoDoubleXY(SNumContrNANivMad, DNumContrNANivMad, "Nivel " + (i + 1));
                    LPuntos.Add(PuntoContrNA);
                    //[0]= SI, [1]=NO [2]=PARC [3]=NO APLICA [4]=TOTAL
                    int[] RespCtrlNivelMadurez = new int[5];
                    //Respuestas Nivel i
                    RespCtrlNivelMadurez[0] = (int)DNumContrSINivMad;
                    RespCtrlNivelMadurez[1] = (int)DNumContrNONivMad;
                    RespCtrlNivelMadurez[2] = (int)DNumContrPARCNivMad;
                    RespCtrlNivelMadurez[3] = (int)DNumContrNANivMad;
                    RespCtrlNivelMadurez[4] = (int)DNumContrNivMadurez;
                    String SCumplimientoNivMadurezi = "% Cumplimiento";
                    double DCumplimientoNivMadurezi = EmpresasFactory.CumplimientoNivelMadurez(RespCtrlNivelMadurez);
                    PuntoDoubleXY PuntoCumpNivMad = new PuntoDoubleXY(SCumplimientoNivMadurezi, DCumplimientoNivMadurezi, "Nivel " + (i + 1));
                    LPuntos.Add(PuntoCumpNivMad);
                }

            }
            return LPuntos;
        }

        //Método que formatea las respuesta de los controles para un Informe según objetivos de Control 1 de 2
        public static List<PuntoIntXY> RecogeControlesDominioInforme1de2XY(int IdInforme)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            List<PuntoIntXY> LControlesDominio = new List<PuntoIntXY>();
            //Recogemos los primeros Dominios de Control
            IQueryable<Dominios> Dominios1 = DominiosFactory.RecogeDominio1de2();
            //Por cada dominio
            foreach (Dominios Dom in Dominios1)
            {
                //Creamos la lista de respuestas de todos los controles de un dominio
                List<int> LControlesTotalDominio = new List<int>();
                //Inicializamos a 0
                for (int i = 0; i < 4; i++)
                {
                    LControlesTotalDominio.Add(0);
                }
                //Recogemos los objetivos de cada dominio
                List<int> LIdObjetivosControl = ObjetivosControlFactory.IdObjetivosControlDominio(Dom.IdDominios);
                //Por cada objetivo de control asociado recogemos las respuestas de los controles de la empresa asociados
                for (int i = 0; i < LIdObjetivosControl.Count; i++)
                {
                    int IdObjControlActual = LIdObjetivosControl[i];
                    List<int> LControlesObjControl = ControlesEmpresaInformeFactory.RecogeRespControlObjControlInf(IdInforme, IdObjControlActual);
                    for (int j = 0; j < LControlesTotalDominio.Capacity; j++)
                    {
                        LControlesTotalDominio[j] = LControlesTotalDominio[j] + LControlesObjControl[j];
                    }
                }
                //Respuestas SI
                PuntoIntXY NuevoPuntoSI = new PuntoIntXY();
                NuevoPuntoSI.X = "SI";
                NuevoPuntoSI.Y = LControlesTotalDominio[0];
                NuevoPuntoSI.Serie = Dom.Nombre;
                LControlesDominio.Add(NuevoPuntoSI);
                //Respuestas NO
                PuntoIntXY NuevoPuntoNO = new PuntoIntXY();
                NuevoPuntoNO.X = "NO";
                NuevoPuntoNO.Y = LControlesTotalDominio[1];
                NuevoPuntoNO.Serie = Dom.Nombre;
                LControlesDominio.Add(NuevoPuntoNO);
                //Respuestas PARC
                PuntoIntXY NuevoPuntoPARC = new PuntoIntXY();
                NuevoPuntoPARC.X = "Parcialmente";
                NuevoPuntoPARC.Y = LControlesTotalDominio[2];
                NuevoPuntoPARC.Serie = Dom.Nombre;
                LControlesDominio.Add(NuevoPuntoPARC);
                //Respuestas NA
                PuntoIntXY NuevoPuntoNA = new PuntoIntXY();
                NuevoPuntoNA.X = "No Aplica";
                NuevoPuntoNA.Y = LControlesTotalDominio[3];
                NuevoPuntoNA.Serie = Dom.Nombre;
                LControlesDominio.Add(NuevoPuntoNA);
            }
            return LControlesDominio;
        }

        //Método que formatea las respuesta de los controles para un Informe según objetivos de Control 2 de 2
        public static List<PuntoIntXY> RecogeControlesDominioInforme2de2XY(int IdInforme)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            List<PuntoIntXY> LControlesDominio = new List<PuntoIntXY>();
            //Recogemos los primeros Dominios de Control
            IQueryable<Dominios> Dominios1 = DominiosFactory.RecogeDominio2de2();
            //Por cada dominio
            foreach (Dominios Dom in Dominios1)
            {
                //Creamos la lista de respuestas de todos los controles de un dominio
                List<int> LControlesTotalDominio = new List<int>();
                //Inicializamos a 0
                for (int i = 0; i < 4; i++)
                {
                    LControlesTotalDominio.Add(0);
                }
                //Recogemos los objetivos de cada dominio
                List<int> LIdObjetivosControl = ObjetivosControlFactory.IdObjetivosControlDominio(Dom.IdDominios);
                //Por cada objetivo de control asociado recogemos las respuestas de los controles de la empresa asociados
                for (int i = 0; i < LIdObjetivosControl.Count; i++)
                {
                    int IdObjControlActual = LIdObjetivosControl[i];
                    //Respuestas de Controles por Objetivo de Control
                    List<int> LControlesObjControl = ControlesEmpresaInformeFactory.RecogeRespControlObjControlInf(IdInforme, IdObjControlActual);
                    for (int j = 0; j < LControlesTotalDominio.Capacity; j++)
                    {
                        LControlesTotalDominio[j] = LControlesTotalDominio[j] + LControlesObjControl[j];
                    }
                }
                //Respuestas SI
                PuntoIntXY NuevoPuntoSI = new PuntoIntXY();
                NuevoPuntoSI.X = "SI";
                NuevoPuntoSI.Y = LControlesTotalDominio[0];
                NuevoPuntoSI.Serie = Dom.Nombre;
                LControlesDominio.Add(NuevoPuntoSI);
                //Respuestas NO
                PuntoIntXY NuevoPuntoNO = new PuntoIntXY();
                NuevoPuntoNO.X = "NO";
                NuevoPuntoNO.Y = LControlesTotalDominio[1];
                NuevoPuntoNO.Serie = Dom.Nombre;
                LControlesDominio.Add(NuevoPuntoNO);
                //Respuestas PARC
                PuntoIntXY NuevoPuntoPARC = new PuntoIntXY();
                NuevoPuntoPARC.X = "Parcialmente";
                NuevoPuntoPARC.Y = LControlesTotalDominio[2];
                NuevoPuntoPARC.Serie = Dom.Nombre;
                LControlesDominio.Add(NuevoPuntoPARC);
                //Respuestas NA
                PuntoIntXY NuevoPuntoNA = new PuntoIntXY();
                NuevoPuntoNA.X = "No Aplica";
                NuevoPuntoNA.Y = LControlesTotalDominio[3];
                NuevoPuntoNA.Serie = Dom.Nombre;
                LControlesDominio.Add(NuevoPuntoNA);
            }
            return LControlesDominio;
        }

        public static List<ControlesEmpresaDatosInforme> RecogeControlesInformeTabla(int IdInforme)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            List<ControlesEmpresaDatosInforme> ControlesEmpr = (from ContrInf in agenteBD.ControlesEmpresaInformeEstablecer
                                                                join Contr in agenteBD.ControlesEstablecer on ContrInf.IdControl equals Contr.IdControl
                                                                join ObjCtr in agenteBD.ObjetivosControlEstablecer on Contr.IdObjControl equals ObjCtr.IdObjControl
                                                                where ContrInf.IdInforme == IdInforme
                                                                select new ControlesEmpresaDatosInforme
                                                                {
                                                                    IdControl = ContrInf.IdControl,
                                                                    Nombre = Contr.Nombre,
                                                                    ObjControl = ObjCtr.Nombre,
                                                                    Respuesta = ContrInf.ValorInforme
                                                                }).ToList();
            //Recorremos la Lista de ControlesEmpresaInforme para formatear el atributo Valor para mostrarlo en una tabla del Informe
            foreach (ControlesEmpresaDatosInforme ControlEmp in ControlesEmpr)
            {
                ControlEmp.Respuesta = ControlesEmpresaDatosInforme.FormateaValorControlEmpresa(ControlEmp.Respuesta);
            }
            return ControlesEmpr;
        }

        //Método que recoge los valores de los controles asociados a un Informe base
        public static List<ControlesEvolucionInforme> ControlesInformeBase(int IdInforme)
        {
            List<ControlesEvolucionInforme> LControlesBase = new List<ControlesEvolucionInforme>();
            ModeloContainer agenteBD = new ModeloContainer();
            LControlesBase = (from ContrInf in agenteBD.ControlesEmpresaInformeEstablecer
                              join Contr in agenteBD.ControlesEstablecer on ContrInf.IdControl equals Contr.IdControl
                              join ObjCtr in agenteBD.ObjetivosControlEstablecer on Contr.IdObjControl equals ObjCtr.IdObjControl
                              where ContrInf.IdInforme == IdInforme
                              select new ControlesEvolucionInforme
                              {
                                  IdControl = ContrInf.IdControl,
                                  IdInformeBase = ContrInf.IdInforme,
                                  Nombre = Contr.Nombre,
                                  RespuestaBase = ContrInf.ValorInforme
                              }).OrderBy(c => c.IdControl).ToList();
            //Recorremos la Lista para formatear los controles a la tabla del informe
            foreach (ControlesEvolucionInforme ControlInf in LControlesBase)
            {
                ControlInf.RespuestaBase = ControlesEmpresaDatosInforme.FormateaValorControlEmpresa(ControlInf.RespuestaBase);
            }
            return LControlesBase;
        }

        //Método que recoge la evolución en las respuestas de los controles según una lista de Informes para formatear en una tabla
        public static List<ControlesEvolucionInforme> ControlesEvolucionInformes(List<int> LInformes)
        {
            ModeloContainer agenteBD = new ModeloContainer();
            LInformes.Sort();
            List<ControlesEvolucionInforme> LControlesEvolucionRespuesta = new List<ControlesEvolucionInforme>();
            //Recogemos las respuestas de los controles del Informe Base
            for (int i = 0; i < LInformes.Count(); i++)
            {
                int IdInformeBase = LInformes[i];
                //Pasamos por cada Informe viendo sus controles y comparándolos con los Informe Base
                for (int j = (i + 1); j < (LInformes.Count); j++)
                {
                    int IdInformeActual = LInformes[j];
                    List<ControlesEmpresaInforme> ControlesDistintos = ControlesEmpresaInformeFactory.ControlesEvolucionInformes(IdInformeBase, IdInformeActual);
                    //Recorremos los activos eliminados y los añadimos a la lista si no habían sido añadidos anteriormente
                    foreach (ControlesEmpresaInforme ControlDistinto in ControlesDistintos)
                    {
                        ControlesEmpresaInforme ControlViejo = (from CtrInf in agenteBD.ControlesEmpresaInformeEstablecer
                                                                where CtrInf.IdControl == ControlDistinto.IdControl && CtrInf.IdInforme == IdInformeBase
                                                                select CtrInf).Single();
                        ControlesEmpresaInforme ControlCambiado = (from CtrInf in agenteBD.ControlesEmpresaInformeEstablecer
                                                                   where CtrInf.IdControl == ControlDistinto.IdControl && CtrInf.IdInforme == IdInformeActual
                                                                   select CtrInf).Single();

                        bool nuevoActivo = true;
                        for (int k = 0; k < LControlesEvolucionRespuesta.Count(); k++)
                        {
                            if (LControlesEvolucionRespuesta[k].IdControl == ControlCambiado.IdControl &&
                                LControlesEvolucionRespuesta[k].RespuestaActual == ControlCambiado.ValorInforme)
                            {
                                nuevoActivo = false;
                            }
                        }
                        if (nuevoActivo)
                        {
                            ControlesEvolucionInforme ControlNuevaRespuesta = new ControlesEvolucionInforme();
                            ControlNuevaRespuesta.IdControl = ControlCambiado.IdControl;
                            ControlNuevaRespuesta.IdInformeBase = IdInformeBase;
                            ControlNuevaRespuesta.IdInformeActual = IdInformeActual;
                            ControlNuevaRespuesta.Nombre = ControlesFactory.NombreControl(ControlCambiado.IdControl);
                            ControlNuevaRespuesta.RespuestaBase = ControlViejo.ValorInforme;
                            ControlNuevaRespuesta.RespuestaActual = ControlCambiado.ValorInforme;
                            LControlesEvolucionRespuesta.Add(ControlNuevaRespuesta);
                        }
                    }
                }
            }
            //Deserializamos las respuestas de los controles
            foreach (ControlesEvolucionInforme ControlInforme in LControlesEvolucionRespuesta)
            {
                ControlInforme.RespuestaBase = ControlesEmpresaNegocio.DesSerializaRespuesta(ControlInforme.RespuestaBase);
                ControlInforme.RespuestaActual = ControlesEmpresaNegocio.DesSerializaRespuesta(ControlInforme.RespuestaActual);
            }
            return LControlesEvolucionRespuesta;
        }
    }
}
